﻿using CloudClipboard.Types;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace CloudClipboard
{
    public class CloudClipBoardBiz
    {
        private DateTime lastClipboardUpdate = DateTime.Now;
        private CloudClipboardClient cloudClipboardClient = null;
        private bool isWaitSendData = false;
        private DateTime lastAlive = DateTime.Now;

        public ClientStatusEnum ClientStatus { get; private set; }

        public CloudClipBoardBiz()
        {
            this.cloudClipboardClient = new CloudClipboardClient(CloudClipboardHelper.Config.ServerHost, CloudClipboardHelper.Config.ServerPort);

            this.cloudClipboardClient.OnClose += this.cloudClipboardClient_OnClose;
            this.cloudClipboardClient.OnConnect += this.cloudClipboardClient_OnConnect;
            this.cloudClipboardClient.OnRecvComplete += this.cloudClipboardClient_OnRecvComplete;
            this.cloudClipboardClient.OnSend += this.cloudClipboardClient_OnSend;
            this.cloudClipboardClient.OnRecving += this.cloudClipboardClient_OnRecving;

            this.LoopHeartBeat();
        }

        void cloudClipboardClient_OnRecving(object sender, EventArgs e)
        {
            this.ClientStatus = ClientStatusEnum.Recving;
            this.lastAlive = DateTime.Now;
        }

        void cloudClipboardClient_OnRecvComplete(object sender, RecvPkgDataEventArgs e)
        {
            UInt32 dwCmd = 0;
            byte[] data = CloudClipboardHelper.DeSerializeCmd(out dwCmd, e.Data);

            Debug.WriteLine(string.Format("OnRecvComplete:{0}", e.Data == null ? "NULL" : e.Data.Length.ToString()));

            if (dwCmd == CommandValues.Cmd_RecvClipboardData)
            {
                ClipboardDataInfo oClipboardDataInfo = CloudClipboardHelper.DeSerializeClipboardData(data);

                MainForm.Current.Invoke(new Action<ClipboardDataInfo>(CloudClipboardHelper.SetClipboardData), oClipboardDataInfo);

                Debug.WriteLine("接受到数据");
                this.lastAlive = DateTime.Now; 

                this.ClientStatus = ClientStatusEnum.Recving;
                CloudClipboardHelper.LoopCall(1, new TimeSpan(0, 0, 0, 2), (t) =>
                {
                    this.ClientStatus = ClientStatusEnum.Normal;
                    return true;
                });
            }
            else if (dwCmd == CommandValues.Cmd_RecvHeartbeatResult)
            {
                Debug.WriteLine("心跳回应包");
                this.ClientStatus = ClientStatusEnum.Normal;
                this.lastAlive = DateTime.Now;
            }
        }

        void cloudClipboardClient_OnConnect(object sender, EventArgs e)
        {
            this.ClientStatus = ClientStatusEnum.Normal;
            this.lastAlive = DateTime.Now;
        }

        void cloudClipboardClient_OnClose(object sender, EventArgs e)
        {
            this.ClientStatus = ClientStatusEnum.Disconnect;
        }

        void cloudClipboardClient_OnSend(object sender, EventArgs e)
        {
            CloudClipboardHelper.LoopCall(1, new TimeSpan(0, 0, 0, 2), (t) =>
            {
                this.ClientStatus = ClientStatusEnum.Normal;
                return true;
            });
        }

        public void NotifyClipBoardChange()
        {
            if (CloudClipboardHelper.CheckIsSupportDataType() == false)
            {
                return;
            }

            this.ClientStatus = ClientStatusEnum.Sending;
            if (this.isWaitSendData == true)
            {
                this.lastClipboardUpdate = DateTime.Now;
                return;
            } 

            this.isWaitSendData = true;

            CloudClipboardHelper.LoopCall(0, new TimeSpan(), (times) =>
            {
                if (DateTime.Now - this.lastClipboardUpdate > new TimeSpan(0, 0, 0, 2))
                {
                    byte[] bytes = CloudClipboardHelper.GetClipboardData();

                    if (bytes != null)
                    {
                        bytes = CloudClipboardHelper.SerializeCmd(CommandValues.Cmd_SendClipboardData, bytes);
                        this.cloudClipboardClient.SendData(bytes);
                    }

                    this.isWaitSendData = false;
                    return false;
                }

                return true;
            });
        }

        public void ConnectToServer()
        {
            this.cloudClipboardClient.ConnectToServer();
        }

        public void Close()
        {
            this.cloudClipboardClient.Close();
        }

        private void LoopHeartBeat()
        {
            CloudClipboardHelper.LoopCall(0, new TimeSpan(0, 0, 0, 10), (t) =>
            {
                if (this.cloudClipboardClient.IsConnected)
                { 
                    //客户哈希值
                    byte[] clientGroupHashCodeBytes = BitConverter.GetBytes(CloudClipboardHelper.Config.GroupHashCode);
                    byte[] bytes = CloudClipboardHelper.SerializeCmd(CommandValues.Cmd_SendHeartbeat, clientGroupHashCodeBytes);
                    this.cloudClipboardClient.SendData(bytes);
                }
                else
                {
                    this.cloudClipboardClient.ConnectToServer();
                    this.lastAlive = DateTime.Now;
                }

                if (DateTime.Now - this.lastAlive > new TimeSpan(0, 0, 0, 25))
                {
                    this.ClientStatus = ClientStatusEnum.Disconnect;
                    this.cloudClipboardClient.Close();
                    this.cloudClipboardClient.ConnectToServer();
                }

                return true;
            });
        }
    }
}
